import { Service } from '../types/index.js';
import { getStorage, setStorage } from '../utils/storage.js';

/**
 * 国际化服务
 * 提供多语言支持、语言切换和翻译功能
 */
class I18nService extends Service {
  constructor(container, options = {}) {
    super(container, options);
    
    // 默认配置
    this.config = {
      defaultLocale: 'zh-CN',
      fallbackLocale: 'zh-CN',
      storageKey: 'admin_locale',
      ...(this.container.config?.admin?.i18n || {})
    };
    
    // 语言包存储
    this.locales = {};
    
    // 当前语言
    this.currentLocale = null;
    
    // 事件监听器
    this.listeners = new Map();
    
    // 保存默认语言包
    this.defaultMessages = options.defaultMessages || {};
  }

  /**
   * 启动服务
   */
  async boot() {
    // 尝试从本地存储获取用户语言偏好
    const savedLocale = getStorage(this.config.storageKey);
    
    // 设置当前语言
    this.currentLocale = savedLocale || this.config.defaultLocale;
    
    // 首先加载默认语言包（如果有）
    if (Object.keys(this.defaultMessages).length > 0) {
      for (const [locale, messages] of Object.entries(this.defaultMessages)) {
        this.addMessages(locale, messages);
        this.logger.info(`Loaded default messages for locale: ${locale}`);
      }
    }
    
    // 尝试加载服务器语言包（可能包含更新的或额外的翻译）
    await this.loadLocale(this.currentLocale);
    
    // 自动加载回退语言包（如果与当前语言不同）
    if (this.currentLocale !== this.config.fallbackLocale) {
      await this.loadLocale(this.config.fallbackLocale);
    }
    
    this.logger.info(`i18n service booted, current locale: ${this.currentLocale}`);
  }

  /**
   * 关闭服务
   */
  async shutdown() {
    this.listeners.clear();
    this.logger.info('i18n service shutdown');
  }

  /**
   * 加载语言包
   * @param {string} locale 语言代码
   * @param {object} messages 语言包内容（可选，如不提供则尝试从服务器加载）
   */
  async loadLocale(locale, messages = null) {
    // 如果已加载，则不再重复加载
    if (this.locales[locale] && !messages) {
      return;
    }
    
    // 如果未提供消息，则尝试从服务器加载
    if (!messages && this.container.has('api')) {
      try {
        const apiService = this.container.get('api');
        const response = await apiService.get(`/i18n/${locale}`);
        messages = response.data;
      } catch (error) {
        this.logger.warn(`Failed to load locale ${locale} from server, using empty messages:`, error);
        messages = {};
      }
    }
    
    // 合并现有消息和新消息
    this.locales[locale] = {
      ...(this.locales[locale] || {}),
      ...(messages || {})
    };
    
    this.logger.info(`Locale ${locale} loaded`);
  }

  /**
   * 添加语言包消息
   * @param {string} locale 语言代码
   * @param {string} key 消息键
   * @param {string|object} value 消息值或嵌套对象
   */
  addMessage(locale, key, value) {
    if (!this.locales[locale]) {
      this.locales[locale] = {};
    }
    
    // 支持嵌套键（如 'user.profile.name'）
    const keys = key.split('.');
    let target = this.locales[locale];
    
    for (let i = 0; i < keys.length - 1; i++) {
      if (!target[keys[i]]) {
        target[keys[i]] = {};
      }
      target = target[keys[i]];
    }
    
    target[keys[keys.length - 1]] = value;
  }

  /**
   * 切换当前语言
   * @param {string} locale 语言代码
   */
  async setLocale(locale) {
    if (this.currentLocale === locale) {
      return;
    }
    
    // 加载目标语言包（如果尚未加载）
    if (!this.locales[locale]) {
      await this.loadLocale(locale);
    }
    
    // 更新当前语言
    this.currentLocale = locale;
    
    // 保存到本地存储
    setStorage(this.config.storageKey, locale);
    
    // 触发语言变更事件
    this.emit('localeChanged', locale);
    
    this.logger.info(`Switched locale to ${locale}`);
  }

  /**
   * 获取当前语言
   * @returns {string} 当前语言代码
   */
  getLocale() {
    return this.currentLocale;
  }

  /**
   * 翻译文本
   * @param {string} key 翻译键
   * @param {object} params 替换参数
   * @param {string} locale 目标语言（可选，默认为当前语言）
   * @returns {string} 翻译后的文本
   */
  t(key, params = {}, locale = null) {
    const targetLocale = locale || this.currentLocale;
    let message = this.getMessageFromKey(targetLocale, key);
    
    // 如果在当前语言中未找到，则尝试回退语言
    if (!message && targetLocale !== this.config.fallbackLocale) {
      message = this.getMessageFromKey(this.config.fallbackLocale, key);
    }
    
    // 如果仍未找到，则返回原始键
    if (!message) {
      return key;
    }
    
    // 替换参数
    return this.replaceParams(message, params);
  }

  /**
   * 从语言包中获取消息
   * @param {string} locale 语言代码
   * @param {string} key 消息键
   * @returns {string|null} 消息文本或null（如果未找到）
   */
  getMessageFromKey(locale, key) {
    if (!this.locales[locale]) {
      return null;
    }
    
    const keys = key.split('.');
    let value = this.locales[locale];
    
    for (const k of keys) {
      if (!value || !Object.prototype.hasOwnProperty.call(value, k)) {
        return null;
      }
      value = value[k];
    }
    
    return typeof value === 'string' ? value : null;
  }

  /**
   * 替换消息中的参数
   * @param {string} message 消息文本
   * @param {object} params 替换参数
   * @returns {string} 替换后的文本
   */
  replaceParams(message, params) {
    let result = message;
    
    for (const [key, value] of Object.entries(params)) {
      // 支持 {param} 和 ${param} 两种格式
      const regex1 = new RegExp(`\\{${key}\\}`, 'g');
      const regex2 = new RegExp(`\\$\\{${key}\\}`, 'g');
      
      result = result.replace(regex1, value).replace(regex2, value);
    }
    
    return result;
  }

  /**
   * 注册事件监听器
   * @param {string} event 事件名称
   * @param {function} listener 事件监听器
   */
  on(event, listener) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(listener);
  }

  /**
   * 移除事件监听器
   * @param {string} event 事件名称
   * @param {function} listener 事件监听器
   */
  off(event, listener) {
    if (this.listeners.has(event)) {
      const listeners = this.listeners.get(event);
      const index = listeners.indexOf(listener);
      if (index > -1) {
        listeners.splice(index, 1);
      }
    }
  }

  /**
   * 触发事件
   * @param {string} event 事件名称
   * @param  {...any} args 事件参数
   */
  emit(event, ...args) {
    if (this.listeners.has(event)) {
      for (const listener of this.listeners.get(event)) {
        try {
          listener(...args);
        } catch (error) {
          this.logger.error(`Error in i18n event listener for ${event}:`, error);
        }
      }
    }
  }

  /**
   * 获取所有支持的语言
   * @returns {Array<string>} 语言代码列表
   */
  getSupportedLocales() {
    return Object.keys(this.locales);
  }

  /**
   * 批量添加翻译消息
   * @param {string} locale 语言代码
   * @param {object} messages 消息对象
   */
  addMessages(locale, messages) {
    if (!this.locales[locale]) {
      this.locales[locale] = {};
    }
    
    // 深度合并
    this.locales[locale] = this.deepMerge(this.locales[locale], messages);
  }

  /**
   * 深度合并对象
   * @param {object} target 目标对象
   * @param {object} source 源对象
   * @returns {object} 合并后的对象
   */
  deepMerge(target, source) {
    const result = { ...target };
    
    for (const key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
          if (!result[key]) {
            result[key] = {};
          }
          result[key] = this.deepMerge(result[key], source[key]);
        } else {
          result[key] = source[key];
        }
      }
    }
    
    return result;
  }
}

export default I18nService;